﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace Medianamik.Core
{
    public class Param
    {
        private const char SEPARATOR = ',';

        public Param(Guid pPropertyID, params object[] pValues)
        {
            PropertyID = pPropertyID;
            Values = pValues.ToList().AsReadOnly();
        }

        public Param(string typeName, string propertyName, params object[] pValues)
        {
            if (String.IsNullOrEmpty(typeName))
                throw new ArgumentException("Type name cannot be null or emty.", "typeName");

            if (String.IsNullOrEmpty(propertyName))
                throw new ArgumentException("Property name cannot be null or emty.", "propertyName");

            var type = NodeTypeManager.GetNodeType(typeName);

            if (type == null)
                throw new Exception("No type found with name " + typeName);

            var property = type.GetAllProperties().FirstOrDefault(p => p.Name.Equals(propertyName));

            if (property == null)
                throw new Exception("No property found with name " + propertyName + " for type " + typeName + ".");

            PropertyID = property.ID;
            Values = pValues.ToList().AsReadOnly();
        }

        public int? Revision
        {
            get;
            set;
        }

        public Guid PropertyID
        {
            get;
            private set;
        }

        public ReadOnlyCollection<object> Values
        {
            get;
            private set;
        }

        public IEnumerable<string> StringValues
        {
            get
            {
                foreach (var val in Values)
                {
                    string valueStr;

                    if (val is string)
                    {
                        valueStr = (string)val;
                    }
                    else
                    {

                        var tc = TypeDescriptor.GetConverter(val.GetType());
                        valueStr = tc.ConvertToInvariantString(val);
                    }

                    yield return valueStr;
                }
            }
        }

        /// <summary>
        /// Retourne la liste des valeurs séparées par le SEPARATOR
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            var sb = new StringBuilder();

            foreach (var s in StringValues)
            {
                sb.Append(s);
                sb.Append(SEPARATOR);
            }

            return sb.ToString().TrimEnd(SEPARATOR);
        }

        /// <summary>
        /// Génère un HashCode à partir des propriété et des valeurs du paramètre
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return string.Concat(PropertyID
                , Revision ?? int.MaxValue
                , ToString()).GetHashCode();

        }
    }
}
